package com.ruoyi.common.utils;

import org.apache.commons.io.FileUtils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Arrays;

public class AESUtil {
	private final static String ENCRYPT_MODE = "AES/ECB/PKCS5Padding";
	private final static String ALGORITHM = "SHA1PRNG";
	private final static String KEY_ALGORITHM = "AES";
	private final static int KEYSIZE = 128;
	private SecretKey nAesKey;
	private byte[] mPublicKey;

	/** 构造方法(不指定PublicKey，通过PublicKey随机生成AesKey) */
	public AESUtil() {
		mPublicKey = generateAesKey();
		nAesKey = new SecretKeySpec(mPublicKey, KEY_ALGORITHM);
	}

	/**
	 * 构造方法(指定PublicKey，通过PublicKey指定生成AesKey)
	 * 
	 * @param key
	 *            密码
	 */
	public AESUtil(byte[] key) {
		mPublicKey = key;
		nAesKey = new SecretKeySpec(mPublicKey, KEY_ALGORITHM);
	}

	/**
	 * 加密
	 * 
	 * @param src
	 *            待加密数据
	 * @return
	 * @throws Exception
	 */
	public byte[] encrypt(byte[] src) throws Exception {

		try {
			Cipher c = Cipher.getInstance(ENCRYPT_MODE);
			c.init(Cipher.ENCRYPT_MODE, nAesKey);
			byte[] data = c.doFinal(src);
			return Arrays.copyOf(data, data.length + 1);// 多加一个byte
		} catch (Exception ex) {
			throw ex;
		}
	}

	/**
	 * 解密
	 * 
	 * @param src
	 *            待解密数据
	 * @return
	 * @throws Exception
	 */
	public byte[] decrypt(byte[] src) throws Exception {
		try {
			Cipher c = Cipher.getInstance(ENCRYPT_MODE);
			c.init(Cipher.DECRYPT_MODE, nAesKey);
			int i = src.length % 16;
			byte[] target;
			if (i > 0) {
				target = Arrays.copyOf(src, src.length - i);// 减去一个byte
			} else {
				target = src;
			}
			return c.doFinal(target);
		} catch (Exception ex) {
			throw ex;
		}
	}

	/**
	 * 获得公钥
	 * 
	 * @return
	 */
	public byte[] getPublicKey() {
		return mPublicKey;
	}

	private byte[] generateAesKey() {
		KeyGenerator keyGenerator = null;
		try {
			keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		keyGenerator.init(KEYSIZE);
		SecretKey secretKey = keyGenerator.generateKey();
		return secretKey.getEncoded();
	}

	private byte[] generateAesKey(byte[] key) {
		KeyGenerator keyGenerator = null;
		SecureRandom secureRandom = null;
		try {
			keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
			secureRandom = SecureRandom.getInstance(ALGORITHM);
			secureRandom.setSeed(key);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		keyGenerator.init(KEYSIZE, secureRandom);
		SecretKey secretKey = keyGenerator.generateKey();
		return secretKey.getEncoded();
	}

	public static void main(String[] args) throws Exception {
		AESUtil util = new AESUtil("13f439726d2d4522".getBytes());
		byte[] bytes = util.encrypt("超级敢死队".getBytes());
		File file = new File("/data/api/test");
		file = new File("E:/one.txt");
		// FileUtils.writeByteArrayToFile(file, bytes);
		byte[] bytese = util.decrypt(FileUtils.readFileToByteArray(file));
		// bytes = util.decrypt(bytes);
		System.out.println(new String(bytese));

		Class.forName("org.sqlite.JDBC");

		Connection conn = DriverManager.getConnection("jdbc:sqlite:F:/chinese_data/8W/conflict_by_db/mrg/zidian_encrypt_blob.db");
		Statement stat = conn.createStatement();
		// stat.executeUpdate("drop table if exists test;");
		// stat.executeUpdate("create table test (_id INT, data BLOB);");
		// PreparedStatement prep =
		// conn.prepareStatement("insert into test values (?, ?);");

		// prep.setString(1, "1");
		// prep.setBytes(2, bytes);
		// prep.addBatch();
		//
		// conn.setAutoCommit(false);
		// prep.executeBatch();
		// conn.setAutoCommit(true);

		ResultSet rs = stat.executeQuery("select * from zi where zi = '二'");
		while (rs.next()) {
			System.out.println("_id = " + rs.getString("_id"));
			// Blob blob = rs.getBlob("zhujie");
			FileUtils.writeByteArrayToFile(new File("E:/two.txt"), rs.getBytes("zhujie"));
			System.out.println("data = " + new String(util.decrypt(rs.getBytes("zhujie"))));
		}
		rs.close();
		conn.close();
	}
}